<?php

namespace IDock\Insurance\TPBX\Request;

use Exception;
use IDock\Insurance\TPBX\Response\PremiumInquiryResponse;
use IDock\Insurance\TPBX\TPBXEnums;
use IDock\Printer\NonCar\NonCarSubCoveragePrinter;
use IDock\Visitor\NonCar\NonCarProductVisitor;
use IDock\Visitor\Premium\PremiumChargingPileVisitor;
use IDock\Visitor\Premium\PremiumCoverageVisitor;
use IDock\Visitor\Premium\PremiumInquiryVisitor;
use IDock\Visitor\Premium\PremiumRelationVisitor;

class PremiumInquiryRequest extends AllTPBXRequest
{
    public $route = 'webapi/v1/apply/query-calculate';

    protected $response = PremiumInquiryResponse::class;

    public $requestType = 'V902';

    protected $urlTip = '车险报价';

    /*** @var  PremiumInquiryVisitor $visitor */
    protected $visitor;

    /**
     * @throws Exception
     */
    public function generate(): array
    {
        $this->setConfig($this->visitor->getExtInfoVisitor()->argc);
        $data = [
            'vehicle' => $this->carData(),
            'vehicleOwner' => $this->getOwnerData(),
            'coverageList' => $this->getCoverageList(),
            'applicant' => $this->getApplicant(),
            'insured' => $this->getInsured(),
        ];
        if ($this->visitor->biStartData) {
            $data['bizApply'] = [
                'expireDate' => date('YmdHis', strtotime($this->visitor->biEndData)),
                'planCode' => '109',
                'effectiveDate' => date('YmdHis', strtotime($this->visitor->biStartData)),
            ];
            if ($this->visitor->getVehicleVisitor()->isNewEnergy) {
                $data['bizApply']['planCode'] = '113';
            }
        }
        if ($this->visitor->ciStartData) {
            $data['tpfApply'] = [
                'expireDate' => date('YmdHis', strtotime($this->visitor->ciEndData)),
                'planCode' => '105',
                'effectiveDate' => date('YmdHis', strtotime($this->visitor->ciStartData)),
            ];
            $data['vehicleTax'] = $this->carShipTax();
        }
        //非车保险
        if ($this->visitor->getNonCarInquiryVisitor()->getNonCarList()) {
            $data['planCodeList'] = $this->getNonCarList();
        }
        return $data;
    }

    private function getNonCarList(): array
    {
        $list = [];
        $nonCar = $this->visitor->getNonCarInquiryVisitor()->getNonCarList();
        foreach ($nonCar as $value) {
            /*** @var $value NonCarProductVisitor */
            $tmp = [
                'asAppliWithInsRelaship' => $this->visitor->getApplicantVisitor()->name == $this->visitor->getInsuredVisitor()->name ? '1' : '5',
                "coverageName" => $value->argc['coverageName'] ?? '',
                "productCode" => $value->productCode,
                "effectiveDate" => date('Ymd', strtotime($this->visitor->biStartData ?: $this->visitor->ciStartData)),
                "expireDate" => date('Ymd', strtotime($this->visitor->biEndData ?: $this->visitor->ciEndData)),
                "planCode" => $value->planCode,
                "productName" => $value->argc['productName'] ?? '',
                'nonCoverageList' => []
            ];
            foreach ($value->subCoverage as $item) {
                /*** @var NonCarSubCoveragePrinter $item */
                $tmp['nonCoverageList'][] = [
                    'coverageCode' => $item->subCode,
                    'coverageName' => $item->subName,
                    'insuredAmount' => $item->amount,
                ];
            }
            $list[] = $tmp;
        }
        return $list;
    }

    /**
     * @throws Exception
     */
    private function getApplicant(): array
    {
        return $this->getRelationData($this->visitor->getApplicantVisitor());
    }

    /**
     * @throws Exception
     */
    private function getOwnerData(): array
    {
        return $this->getRelationData($this->visitor->getOwnerVisitor());
    }

    /**
     * @throws Exception
     */
    private function getInsured(): array
    {
        return $this->getRelationData($this->visitor->getInsuredVisitor());
    }

    /**
     * @throws Exception
     */
    private function getRelationData(PremiumRelationVisitor $relation): array
    {
        $arr = [
            'personType' => $relation->typeCode == 'R1' ? '1' : '0',
        ];
        if ($arr['personType'] == '1') {
            $arr['person'] = [
                "birthday" => $this->getBirthday($relation->certificateNo),
                "personnelName" => $relation->name,
                "mobileTelephone" => $relation->mobile,
                "address" => $relation->address,
//                "gender" => $this->getGenderByIDcard($relation->certificateNo),
                "certificateNo" => $relation->certificateNo,
                "email" => $relation->email,
                "certificateType" => TPBXEnums::$certificateTypeCode[$relation->certificateTypeCode] ?? ''
            ];
        } else {
            $arr['group'] = [
                "organName" => $relation->name,
                "agentIdCardType" => TPBXEnums::$certificateTypeCode[$relation->linkManCertificateTypeCode] ?? '',
                "address" => $relation->address,
                "addressDetail" => $relation->address,
                "addressAreaCode" => $relation->areaCode,
                "addressCityCode" => $relation->cityCode,
                "addressProvinceCode" => $relation->provinceCode,
                "linkManMobileTelephone" => $relation->mobile,
                "certificateNo" => $relation->certificateNo,
                "email" => $relation->email,
                "certificateType" => '6',
                "certType" => '1',// 小规模纳税人
                "agentIdCard" => $relation->linkManCertificateNo,
                "taxRegisterNo" => '',//税务登记号
                "postcode" => $relation->postcode,
                'linkManName' => $relation->linkManName,
                'linkManSexCode' => '',
                'businessRegisterId' => '',
                'stateProperty' => '15',//私营企业
                'companyAttribute' => TPBXEnums::$attachNature[$this->visitor->getVehicleVisitor()->attachNature] ?? ''
            ];
            if ($relation->certificateTypeCode != '52') {
                throw new Exception("证件类型仅支持社会信用码");
            }
        }
        return $arr;
    }

    /**
     * @throws Exception
     */
    public function getBirthday($idCard): string
    {
        if (strlen($idCard) != 18) {
            throw new Exception("身份证位数不合法");
        }
        return substr($idCard, 6, 4) . '-' . substr($idCard, 10, 2) . '-' . substr($idCard, 12, 2);
    }

    /**
     * 车辆信息
     * @return array
     * @throws Exception
     */
    private function carData(): array
    {
        $data = [
            'autoModelCode' => $this->visitor->getVehicleVisitor()->vehicleModelCode,
            'fuelType' => TPBXEnums::$energyType[$this->visitor->getVehicleVisitor()->energyTypeCode] ?? '',
            'exhaustCapability' => $this->visitor->getVehicleVisitor()->vehicleExhaust,
            'purchasePrice' => $this->visitor->getVehicleVisitor()->vehiclePriceWithOutTax,
            'firstRegisterDate' => $this->visitor->getVehicleVisitor()->firstRegisterDate ? date('Ymd', strtotime($this->visitor->getVehicleVisitor()->firstRegisterDate)) : '',
            'vehicleBrand' => '',
            'transferDate' => $this->visitor->getVehicleVisitor()->transferDate,
            'vehicleStyle' => $this->visitor->getVehicleVisitor()->vehicleStyleCode,
            'engineNo' => $this->visitor->getVehicleVisitor()->engineNo,
            'vehicleFrameNo' => $this->visitor->getVehicleVisitor()->vin,
            'ownershipAttributeCode' => TPBXEnums::$ownerAttachNature[$this->visitor->getVehicleVisitor()->attachNature],
            'licenseTypeCode' => TPBXEnums::$licenseTypeCode[$this->visitor->getVehicleVisitor()->licenseTypeCode] ?? '',
            'usageAttributeCode' => TPBXEnums::$useNatureCode[$this->visitor->getVehicleVisitor()->useNatureCode] ?? '',
            'weight' => $this->visitor->getVehicleVisitor()->wholeWeight ? round(floatval($this->visitor->getVehicleVisitor()->wholeWeight) / 1000, 2) : '',
//            'customerNegotiatePrice' => '',
            'ecdemicVehicleFlag' => intval(boolval($this->visitor->getVehicleVisitor()->nonlocalCar)),
            'vehicleTonnages' => $this->visitor->getVehicleVisitor()->vehicleTonnage ? round(floatval($this->visitor->getVehicleVisitor()->vehicleTonnage / 1000), 2) : '',
            'vehicleLicenceCode' => $this->visitor->getVehicleVisitor()->licenseNo,
            'vehicleSeats' => $this->visitor->getVehicleVisitor()->vehicleSeat,
            'vehicleType' => TPBXEnums::$carKindCode[$this->visitor->getVehicleVisitor()->carKindCode] ?? '',
        ];

        if ($this->visitor->vehicleVisitor->negotiatedValue) {
            $data['customerNegotiatePrice'] = $this->visitor->vehicleVisitor->negotiatedValue;
        }

        if ($this->visitor->vehicleVisitor->carCertificateNo) {
            $data['VehicleCertificateNo'] = $this->visitor->vehicleVisitor->carCertificateNo;
            $data['VehicleCertificateDate'] = $this->visitor->vehicleVisitor->carCertificateDate ? date('Ymd',strtotime($this->visitor->vehicleVisitor->carCertificateDate)) : '';
            $data['VehicleCertificateType'] = $this->visitor->vehicleVisitor->carCertificateType;
        }

        if (empty($data['licenseTypeCode'])) {
            throw new Exception("不支持该号牌种类");
        }
        if ($this->visitor->getVehicleVisitor()->isTransfer) {
            $data['specialCarFlag'] = '1';
        }
        return $data;
    }

    /**
     * 险种信息
     * @return array
     */
    private function getCoverageList(): array
    {
        $list = [];
        $coverageList = $this->visitor->getCoverageVisitorList();
        $coverageList = array_combine(array_column($coverageList, 'coverageCode'), $coverageList);

        foreach ($coverageList as $coverage) {

            /*** @var PremiumCoverageVisitor $coverage */
            $one = [
                'coverageCode' => TPBXEnums::$coverageCode[$coverage->coverageCode] ?? '',
                'insuredAmount' => $coverage->amount,//保额
            ];

            //车损险保额
            if ($one['coverageCode'] == 'NEAOD' or $one['coverageCode'] == 'AOD') {
                $one['insuredAmount'] = $this->visitor->vehicleVisitor->negotiatedValue ?: $this->visitor->vehicleVisitor->actualValue;
            }
            
            if ($one['coverageCode'] == 'NEAPL' or $one['coverageCode'] == 'APL') {
                $one['insuredAmount'] = $coverage->unitAmount;
                $one['subsidiary'] = $this->visitor->getVehicleVisitor()->vehicleSeat - 1;
            }

            if (in_array($one['coverageCode'], ['AODAECSE', 'ATPAECSE', 'ADLAECSE', 'APLAECSE'])) {
                $one['deductionRate'] = intval($coverage->deductionRate) / 100;
            }
            //三者保外共享
            if ($coverage->coverageCode == 'C03004') {
                $one['sharedCoverageFlag'] = $this->sharedCoverageFlag($coverageList, $coverage->coverageCode, 'C03001');
            }
            if ($coverage->coverageCode == 'C13004') {
                $one['sharedCoverageFlag'] = $this->sharedCoverageFlag($coverageList, $coverage->coverageCode, 'C13001');
            }

            //司机保外共享
            if ($coverage->coverageCode == 'C04003') {
                $one['sharedCoverageFlag'] = $this->sharedCoverageFlag($coverageList, $coverage->coverageCode, 'C04001');
            }
            if ($coverage->coverageCode == 'C14003') {
                $one['sharedCoverageFlag'] = $this->sharedCoverageFlag($coverageList, $coverage->coverageCode, 'C14001');
            }

            //乘客保外共享
            if ($coverage->coverageCode == 'C05003') {
                $one['sharedCoverageFlag'] = $this->sharedCoverageFlag($coverageList, $coverage->coverageCode, 'C05001');
            }
            if ($coverage->coverageCode == 'C15003') {
                $one['sharedCoverageFlag'] = $this->sharedCoverageFlag($coverageList, $coverage->coverageCode, 'C15001');
            }

            if ($coverage->coverageCode == 'C01001') {
                unset($one['insuredAmount']);
            }
            if ($one['coverageCode'] == 'NELSCP' or $one['coverageCode'] == 'NESCPR') {
                $chargingList = [];
                foreach ($this->visitor->getChargingPileVisitorList() as $visitor) {
                    /*** @var PremiumChargingPileVisitor $visitor */
                    $chargingList[] = [
                        "chargingPostType" => $visitor->chargingPileType,
                        "chargingPostCode" => $visitor->chargingPileCode,
                        "chargingPostAddress" => $visitor->chargingPileAddress,
                        "chargingPostAddressType" => TPBXEnums::$chargingPileAddressType[$visitor->chargingPileAddressType] ?? '',
                        "chargingPostKind" => TPBXEnums::$chargingPileKind[$visitor->chargingPileKind] ?? '',
                        "chargingPostYearLimit" => TPBXEnums::$chargingPileYearLimit[$visitor->chargingPileYearLimit] ?? '',
                        "insuredAmount" => $one['coverageCode'] == 'NELSCP' ? $visitor->lossAmount : $visitor->liabilityAmount
                    ];
                }
                $one['chargingPileList'] = $chargingList;
            }
            //安全检测
            if (in_array($coverage->coverageCode, ['C08002', 'C18002'])) {
                $one['setMeal'] = '2';
            }
            //代为送检
            if (in_array($coverage->coverageCode, ['C08004', 'C18004'])) {
                $one['setMeal'] = '2';
            }
            $list[] = $one;
        }
        return $list;
    }

    /**
     * 车船税
     * @return array
     * @throws Exception
     */
    private function carShipTax(): array
    {
        $taxVisitor = $this->visitor->getCarTaxVisitor();

        $arr = [
            'taxConditionCode' => TPBXEnums::$taxTypeCode[$taxVisitor->taxTypeCode] ?? '',
        ];
        if ($arr['taxConditionCode'] == 'C' or $arr['taxConditionCode'] == 'E') {
            $arr['freeNo'] = $taxVisitor->taxDocumentNumber;
            $arr['deductionDueCode'] = TPBXEnums::$taxReductionReasonCode[$taxVisitor->taxReductionReasonCode] ?? '';
            $arr['deductionDueType'] = $taxVisitor->taxReductionCode;
            $arr['certDepartmentName'] = $taxVisitor->taxDepartment;
            if ($arr['deductionDueType'] == 'A') {
                $arr['deduction'] = $taxVisitor->taxExemption;
            } elseif ($arr['deductionDueType'] == 'P') {
                $arr['deductionDueProportion'] = $taxVisitor->taxFreeRate;
            }
        } elseif ($arr['taxConditionCode'] == 'P') {
            $arr['taxPaidAreaCode'] = $taxVisitor->taxPaidAreaCode;
            $arr['taxDocumentDate'] = $taxVisitor->taxDocumentDate;
            $arr['payNo'] = $taxVisitor->taxDocumentNumber;
        }

        if (empty($arr['taxConditionCode'])) {
            throw new Exception("不支持该纳税类型");
        }
        return $arr;
    }

    /**
     * 共享保额判定
     * @param $coverageList
     * @param $coverageCode
     * @param $sharedCoverageCode
     * @return int
     */
    private function sharedCoverageFlag($coverageList,$coverageCode, $sharedCoverageCode): int
    {
        if (!isset($coverageList[$coverageCode]) or !isset($coverageList[$sharedCoverageCode])) {
            return 0;
        }

        if ($coverageCode == 'C05003' or $coverageCode == 'C15003') {
            if ($coverageList[$coverageCode]->amount == $coverageList[$sharedCoverageCode]->unitAmount) {
                return 1;
            }
        } else {
            if ($coverageList[$coverageCode]->amount == $coverageList[$sharedCoverageCode]->amount) {
                return 1;
            }
        }

        return 0;
    }
}
